package com.ethink.mdm.service.impl;

import cn.hutool.core.date.DateUtil;
import com.ethink.mdm.api.enums.LegalCurrencyEnum;
import com.ethink.mdm.api.info.LegalCurrencyExchangeRateInfo;
import com.ethink.mdm.api.request.LegalCurrencyExchangeRateListByPubDatesRequest;
import com.ethink.mdm.api.response.LegalCurrencyExchangeRateGetSummaryResponse;
import com.ethink.mdm.api.response.LegalCurrencyExchangeRateListByPubDatesResponse;
import com.ethink.mdm.common.mapper.LegalCurrencyExchangeRateMapper;
import com.ethink.mdm.service.LegalCurrencyExchangeRateService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 法币汇率表 Service接口实现
 *
 * @Author: lzy
 * @Date: Created in 2022/12/8 18:11
 * ModifiedBy:
 * Version:
 */
@Slf4j
@Service
public class LegalCurrencyExchangeRateServiceImpl implements LegalCurrencyExchangeRateService {
    @Autowired
    private LegalCurrencyExchangeRateMapper legalCurrencyExchangeRateMapper;

    @Override
    public LegalCurrencyExchangeRateGetSummaryResponse getLegalCurrencyExchangeRateSummary() {
        LegalCurrencyExchangeRateGetSummaryResponse response = new LegalCurrencyExchangeRateGetSummaryResponse();

        List<LegalCurrencyExchangeRateInfo> exchangeRateInfoList = legalCurrencyExchangeRateMapper.listLegalCurrencyExchangeRateByAimCurrencyCode(LegalCurrencyEnum.CNY.getCode());
        if (CollectionUtils.isNotEmpty(exchangeRateInfoList)) {
            // 发布时间
            response.setPubTime(exchangeRateInfoList.get(0).getPubTime());
            // 汇率列表
            List<LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem> itemList = new ArrayList<>();
            // 外部兑人民币汇率信息
            LegalCurrencyExchangeRateInfo usdCnyExchangeRateInfo = this.getExchangeRateInfoByOrgCurrency(LegalCurrencyEnum.USD, exchangeRateInfoList);
            LegalCurrencyExchangeRateInfo hkdCnyExchangeRateInfo = this.getExchangeRateInfoByOrgCurrency(LegalCurrencyEnum.HKD, exchangeRateInfoList);
            LegalCurrencyExchangeRateInfo eurCnyExchangeRateInfo = this.getExchangeRateInfoByOrgCurrency(LegalCurrencyEnum.EUR, exchangeRateInfoList);
            // 美元兑人民
            LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem usdCnyItem = new LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem();
            usdCnyItem.setOrgCurrencyCode(LegalCurrencyEnum.USD.getCode());
            usdCnyItem.setOrgCurrencyName(LegalCurrencyEnum.USD.getName());
            usdCnyItem.setAimCurrencyCode(LegalCurrencyEnum.CNY.getCode());
            usdCnyItem.setAimCurrencyName(LegalCurrencyEnum.CNY.getName());
            usdCnyItem.setRate(usdCnyExchangeRateInfo.getSpotExchangeSellingRate().setScale(4, BigDecimal.ROUND_HALF_UP));
            itemList.add(usdCnyItem);
            // 美元兑港币
            LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem usdHkdItem = new LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem();
            usdHkdItem.setOrgCurrencyCode(LegalCurrencyEnum.USD.getCode());
            usdHkdItem.setOrgCurrencyName(LegalCurrencyEnum.USD.getName());
            usdHkdItem.setAimCurrencyCode(LegalCurrencyEnum.HKD.getCode());
            usdHkdItem.setAimCurrencyName(LegalCurrencyEnum.HKD.getName());
            usdHkdItem.setRate(usdCnyExchangeRateInfo.getSpotExchangeSellingRate().divide(hkdCnyExchangeRateInfo.getSpotExchangeSellingRate(), 4, BigDecimal.ROUND_HALF_UP));
            itemList.add(usdHkdItem);
            // 美元兑欧元
            LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem usdEurItem = new LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem();
            usdEurItem.setOrgCurrencyCode(LegalCurrencyEnum.USD.getCode());
            usdEurItem.setOrgCurrencyName(LegalCurrencyEnum.USD.getName());
            usdEurItem.setAimCurrencyCode(LegalCurrencyEnum.EUR.getCode());
            usdEurItem.setAimCurrencyName(LegalCurrencyEnum.EUR.getName());
            usdEurItem.setRate(usdCnyExchangeRateInfo.getSpotExchangeSellingRate().divide(eurCnyExchangeRateInfo.getSpotExchangeSellingRate(), 4, BigDecimal.ROUND_HALF_UP));
            itemList.add(usdEurItem);
            // 欧元兑人民
            LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem eurCnyItem = new LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem();
            eurCnyItem.setOrgCurrencyCode(LegalCurrencyEnum.EUR.getCode());
            eurCnyItem.setOrgCurrencyName(LegalCurrencyEnum.EUR.getName());
            eurCnyItem.setAimCurrencyCode(LegalCurrencyEnum.CNY.getCode());
            eurCnyItem.setAimCurrencyName(LegalCurrencyEnum.CNY.getName());
            eurCnyItem.setRate(eurCnyExchangeRateInfo.getSpotExchangeSellingRate().setScale(4, BigDecimal.ROUND_HALF_UP));
            itemList.add(eurCnyItem);
            // 欧元兑港币
            LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem eurHkdItem = new LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem();
            eurHkdItem.setOrgCurrencyCode(LegalCurrencyEnum.EUR.getCode());
            eurHkdItem.setOrgCurrencyName(LegalCurrencyEnum.EUR.getName());
            eurHkdItem.setAimCurrencyCode(LegalCurrencyEnum.HKD.getCode());
            eurHkdItem.setAimCurrencyName(LegalCurrencyEnum.HKD.getName());
            eurHkdItem.setRate(eurCnyExchangeRateInfo.getSpotExchangeSellingRate().divide(hkdCnyExchangeRateInfo.getSpotExchangeSellingRate(), 4, BigDecimal.ROUND_HALF_UP));
            itemList.add(eurHkdItem);
            // 欧元兑美元
            LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem eurUsdItem = new LegalCurrencyExchangeRateGetSummaryResponse.LegalCurrencyExchangeRateListResponseItem();
            eurUsdItem.setOrgCurrencyCode(LegalCurrencyEnum.EUR.getCode());
            eurUsdItem.setOrgCurrencyName(LegalCurrencyEnum.EUR.getName());
            eurUsdItem.setAimCurrencyCode(LegalCurrencyEnum.USD.getCode());
            eurUsdItem.setAimCurrencyName(LegalCurrencyEnum.USD.getName());
            eurUsdItem.setRate(eurCnyExchangeRateInfo.getSpotExchangeSellingRate().divide(usdCnyExchangeRateInfo.getSpotExchangeSellingRate(), 4, BigDecimal.ROUND_HALF_UP));
            itemList.add(eurUsdItem);

            response.setItems(itemList);
        }

        return response;
    }

    @Override
    public List<LegalCurrencyExchangeRateListByPubDatesResponse> listLegalCurrencyExchangeRateByPubDates(LegalCurrencyExchangeRateListByPubDatesRequest request) {
        List<LegalCurrencyExchangeRateListByPubDatesResponse> list = new ArrayList<>();
        // 汇率 = org: aim
        if (LegalCurrencyEnum.USD.getCode().equals(request.getOrgCurrencyCode())) {
            // 美元币种，汇率是1
            for (Date pubDate : request.getPubDates()) {
                LegalCurrencyExchangeRateListByPubDatesResponse response = new LegalCurrencyExchangeRateListByPubDatesResponse();
                response.setPubDate(pubDate);
                response.setOrgCurrencyCode(LegalCurrencyEnum.USD.getCode());
                response.setOrgCurrencyName(LegalCurrencyEnum.USD.getName());
                response.setAimCurrencyCode(LegalCurrencyEnum.USD.getCode());
                response.setAimCurrencyName(LegalCurrencyEnum.USD.getName());
                response.setRate(new BigDecimal(1));
                list.add(response);
            }
            return list;
        }
        // 先查询美元和人民币的汇率
        LegalCurrencyExchangeRateListByPubDatesRequest usdReq = new LegalCurrencyExchangeRateListByPubDatesRequest();
        usdReq.setPubDates(request.getPubDates());
        usdReq.setOrgCurrencyCode(LegalCurrencyEnum.USD.getCode());
        usdReq.setAimCurrencyCode(LegalCurrencyEnum.CNY.getCode());
        List<LegalCurrencyExchangeRateInfo> usdToCnyList = legalCurrencyExchangeRateMapper.listLegalCurrencyExchangeRateByPubDates(usdReq);
        if (CollectionUtils.isEmpty(usdToCnyList)) {
            return list;
        }
        // 如果外币是人民币，直接返回
        if (LegalCurrencyEnum.CNY.getCode().equals(request.getOrgCurrencyCode())) {
            // 美元币种，汇率是1
            for (LegalCurrencyExchangeRateInfo info : usdToCnyList) {
                LegalCurrencyExchangeRateListByPubDatesResponse response = new LegalCurrencyExchangeRateListByPubDatesResponse();
                response.setPubDate(info.getPubDate());
                response.setOrgCurrencyCode(LegalCurrencyEnum.CNY.getCode());
                response.setOrgCurrencyName(LegalCurrencyEnum.CNY.getName());
                response.setAimCurrencyCode(LegalCurrencyEnum.USD.getCode());
                response.setAimCurrencyName(LegalCurrencyEnum.USD.getName());
                response.setRate(new BigDecimal(1).divide(info.getSpotExchangeSellingRate(), 6, BigDecimal.ROUND_HALF_UP));
                list.add(response);
            }
            return list;
        }
        // 美元:人民币
        Map<String, LegalCurrencyExchangeRateInfo> usdToCnyMap = usdToCnyList.stream()
                .collect(Collectors.toMap(info -> DateUtil.formatDate(info.getPubDate()), info -> info));
        // 外币:人民币
        LegalCurrencyExchangeRateListByPubDatesRequest otherReq = new LegalCurrencyExchangeRateListByPubDatesRequest();
        otherReq.setPubDates(request.getPubDates());
        otherReq.setOrgCurrencyCode(request.getOrgCurrencyCode());
        otherReq.setAimCurrencyCode(LegalCurrencyEnum.CNY.getCode());
        List<LegalCurrencyExchangeRateInfo> otherToCnyList = legalCurrencyExchangeRateMapper.listLegalCurrencyExchangeRateByPubDates(otherReq);
        if (CollectionUtils.isEmpty(otherToCnyList)) {
            return list;
        }
        // 外币:美元  = 外币:人民币 * (1/ 美元:人民币)
        for (LegalCurrencyExchangeRateInfo info : otherToCnyList) {
            LegalCurrencyExchangeRateInfo usdToCny = usdToCnyMap.get(DateUtil.formatDate(info.getPubDate()));
            LegalCurrencyExchangeRateListByPubDatesResponse response = new LegalCurrencyExchangeRateListByPubDatesResponse();
            response.setPubDate(info.getPubDate());
            response.setOrgCurrencyCode(info.getOrgCurrencyCode());
            response.setOrgCurrencyName(LegalCurrencyEnum.valueOfCode(info.getOrgCurrencyCode()).getName());
            response.setAimCurrencyCode(LegalCurrencyEnum.USD.getCode());
            response.setAimCurrencyName(LegalCurrencyEnum.USD.getName());
            response.setRate(info.getSpotExchangeSellingRate().divide(usdToCny.getSpotExchangeSellingRate(), 6, BigDecimal.ROUND_HALF_UP));
            list.add(response);
        }
        return list;
    }

    private LegalCurrencyExchangeRateInfo getExchangeRateInfoByOrgCurrency(LegalCurrencyEnum orgCurrency, List<LegalCurrencyExchangeRateInfo> exchangeRateInfoList) {
        List<LegalCurrencyExchangeRateInfo> exchangeRateInfoFilterList = exchangeRateInfoList
                .stream()
                .filter(item -> item.getOrgCurrencyCode().equals(orgCurrency.getCode()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(exchangeRateInfoFilterList)) {
            return null;
        }
        return exchangeRateInfoFilterList.get(0);
    }
}
